home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Code Resources / 3D Buttons CDEF 1.0b4 / Source / 3D Buttons CDEF source / (3D Buttons CDEF.π) / LGBIconButton.cp < prev    next >
Encoding:
Text File  |  1994-07-31  |  14.2 KB  |  545 lines  |  [TEXT/MMCC]

  1. /**************************************************************************
  2.     LGBIconButton
  3.     
  4.     Public domain, by Zig Zichterman.
  5.     
  6.     This class implements 3D icon push buttons according to the guidelines
  7.     suggested in _develop_ 15. Some of the drawing code is taken from
  8.     the public domain source accompanying _develop_ 15.
  9.  
  10.     A new button variant that draws an icon button.  The icon draws
  11.     in a rectangular frame with 3D effects.
  12.     
  13.     LGBIconButton uses contrlValue for the resource id of the icon family.
  14.     You must set contrlValue (and probably contrlMax).
  15.     
  16.     LGBIconButton does not draw a title. Ever. Since it is bad HI to
  17.     display an icon without an accompanying text, you should place a 
  18.     caption near this button to clue the user in to just what your
  19.     icon means.
  20.  
  21.         07/31/94    zz    Draw 3D if 4-bit grey, BW if 4-bit color
  22.         07/31/94    zz    save/restore pen colors
  23.     1.0b2 (never released)
  24.         07/20/94    zz    call PenNormal() before drawing anything!
  25.     1.0b1
  26. **************************************************************************/
  27. #include "LGBIconButton.h"
  28.  
  29. #include <GestaltEqu.h>
  30. #include <Icons.h>
  31.  
  32. #include "LGBControl.h"
  33. #include "LGBDeviceIterator.h"
  34. #include "UGBDraw.h"
  35.  
  36. /**************************************************************************
  37.     Main()                                                        [static]
  38.     
  39.     Main entry point for all icon push button calls. Dispatch according to
  40.     message.
  41. **************************************************************************/
  42. long
  43. LGBIconButton::Main(short inVariation, ControlHandle ioControl,
  44.         short inMsg, long ioParam)
  45. {
  46.     long            returnMe    = 0;
  47.  
  48.     // lock the control handle for the duration of this call
  49.     char state = ::HGetState((Handle) ioControl);
  50.     ::HLock((Handle) ioControl);
  51.     
  52.     LGBIconButton    button(*ioControl);
  53.     
  54.     switch (inMsg) {
  55.         case drawCntl    :
  56.                 button.Draw(ioParam);
  57.                 break;
  58.                             
  59.         case testCntl    :
  60.             {
  61.                 Point    hitPt;
  62.                 hitPt.h    = LoWord(ioParam);
  63.                 hitPt.v    = HiWord(ioParam);
  64.                 if (button.Test(hitPt)) {
  65.                     returnMe = inButton;
  66.                 }
  67.             }
  68.             break;
  69.         
  70.         case calcCRgns    :    // only called in 24-bit mode
  71.             {    // is 32-bit addressing off?
  72.                 long    result    = 0;
  73.                 OSErr    err = ::Gestalt(gestaltAddressingModeAttr,&result);
  74.                 if (!err && ((result &
  75.                         (1L << gestalt32BitAddressing)) == 0)) {
  76.                     RgnHandle    rgn = (RgnHandle)
  77.                                     ::StripAddress((Ptr) ioParam);
  78.                     button.CalcCRgn(rgn);
  79.                 }
  80.             }
  81.             break;
  82.         
  83.         case calcCntlRgn    :    // only called in 32-bit mode
  84.             {
  85.                 button.CalcCRgn((RgnHandle) ioParam);
  86.             }    
  87.             break;
  88.     }
  89.     
  90.     // unlock handle
  91.     ::HSetState((Handle) ioControl,state);
  92.     return returnMe;
  93. }
  94.  
  95. //—————————————————————————————————————————————————————————————————————————
  96. // Constructor
  97. //—————————————————————————————————————————————————————————————————————————
  98.  
  99. /**************************************************************************
  100.     LGBControl(ControlHandle,Boolean)
  101.     
  102.     construct/initialize a control object. Just stash the control
  103.     handle away for the rest of the class to toy with.
  104. **************************************************************************/
  105. LGBIconButton::LGBIconButton(ControlRecord *inControl)
  106.     : mControl(inControl)
  107. {
  108.  
  109. }
  110.  
  111. //—————————————————————————————————————————————————————————————————————————
  112. // Dispatch entry points
  113. //—————————————————————————————————————————————————————————————————————————
  114.  
  115. /**************************************************************************
  116.     Draw()
  117.     
  118.     Draw the control. inPartCode is a part code specifying which part of
  119.     the control to draw, or 0 for the entire control.
  120.     
  121.     icon buttons only have inButton, so we ignore the inPartCode.
  122.  
  123.     Save the current drawing environment. Iterate through all the devices
  124.     (screens), drawing the control in color or black and white depending
  125.     on the screen depth. Once done, restore the drawing environment and
  126.     return.
  127. **************************************************************************/
  128. void
  129. LGBIconButton::Draw(long inPartCode)
  130. {
  131.     // if we're invisible, don't draw
  132.     if (mControl->contrlVis == false) return;
  133.     
  134.     // save the pen colors        // will probably crash SEs, so test first
  135.     RGBColor    fore,back;
  136.     if (UGBDraw::ColorQDIsPresent()) {
  137.         ::GetForeColor(&fore);
  138.         ::GetBackColor(&back);
  139.     }
  140.     
  141.     // save the clip region
  142.     RgnHandle    saveClip    = ::NewRgn();
  143.     if (!saveClip) return;
  144.     ::GetClip(saveClip);
  145.  
  146.     // make the pen something sensible
  147.     ::PenNormal();
  148.     ::ForeColor(blackColor);
  149.     ::BackColor(whiteColor);
  150.         
  151.     // loop through all the devices
  152.     LGBDeviceIterator    device;
  153.     device.Init(mControl->contrlRect);
  154.     short    depth    = 0;
  155.     do {
  156.         depth = device.Next();
  157.         if (depth == 0) break;    // all done with devices
  158.         if ((depth < 4)
  159.                 || (depth == 4 && device.mDeviceIsColor)) {
  160.             DrawBW();
  161.         } else {
  162.             DrawColor();
  163.         }
  164.     } while(true);
  165.  
  166.     // restore the pen
  167.     if (UGBDraw::ColorQDIsPresent()) {
  168.         ::RGBForeColor(&fore);
  169.         ::RGBBackColor(&back);
  170.     }
  171.  
  172.     // restore the clip region
  173.     ::SetClip(saveClip);
  174.     ::DisposeRgn(saveClip);
  175. }
  176.  
  177. /**************************************************************************
  178.     Test()
  179.     
  180.     Return inButton if the point is in our rect, 
  181. **************************************************************************/
  182. Boolean
  183. LGBIconButton::Test(Point inHitPt)
  184. {
  185.     return ::PtInRect(inHitPt,&(mControl->contrlRect));
  186. }
  187.  
  188. /**************************************************************************
  189.     CalcCRgn()
  190.     
  191.     Calculate the control's region in the given region handle
  192. **************************************************************************/
  193. void
  194. LGBIconButton::CalcCRgn(RgnHandle ioRgn)
  195. {
  196.     if (!ioRgn) return;        // idiot resistance
  197.     ::RectRgn(ioRgn,&(mControl->contrlRect));
  198. }
  199.  
  200. //—————————————————————————————————————————————————————————————————————————
  201. // Draw
  202. //—————————————————————————————————————————————————————————————————————————
  203.  
  204. /**************************************************************************
  205.     DrawBW()
  206.     
  207.     Draw the control in black and white
  208. **************************************************************************/
  209. void
  210. LGBIconButton::DrawBW(void)
  211. {
  212.     // Set the pen to black, 1x1
  213.     ::PenNormal();
  214.  
  215.     // erase the insides
  216.     EraseInsides();
  217.     
  218.     // draw the frame
  219.     DrawFrame();
  220.     
  221.     // draw the icon
  222.     DrawIcon(false);
  223.  
  224.     // draw the monochrome 3D effects
  225.     DrawBW3D();
  226.     
  227.     // draw highlight if necessary
  228.     const short hilite = mControl->contrlHilite;
  229.     if (hilite && (hilite != 255)) {
  230.         Rect    invertMe    = mControl->contrlRect;
  231.         ::InsetRect(&invertMe,1,1);
  232.         ::InvertRect(&invertMe);
  233.     }
  234. }
  235.  
  236. /**************************************************************************
  237.     DrawBW3D()
  238.     
  239.     Draw the 3D effects as a 50% grey dither on the bottom right sides
  240. **************************************************************************/
  241. void
  242. LGBIconButton::DrawBW3D(void)
  243. {
  244.     // no 3D on inactive buttons
  245.     if (mControl->contrlHilite == 255) return;
  246.  
  247.     // fabricate a 50% grey pattern on the fly rather
  248.     // than hassle with QD globals and A4 stuff
  249.     unsigned char grey[8];
  250.     grey[0] = grey[2] = grey[4] = grey[6] = 0xAA;
  251.     grey[1] = grey[3] = grey[5] = grey[7] = 0x55;
  252.     ::PenPat((PatPtr) grey);
  253.  
  254.     Rect    box = mControl->contrlRect;
  255.     ::MoveTo(box.right - 2, box.top + 1);
  256.     ::LineTo(box.right - 2, box.bottom - 2);
  257.     ::MoveTo(box.right - 3, box.top + 2);
  258.     ::LineTo(box.right - 3, box.bottom - 3);
  259.     
  260.     ::MoveTo(box.left + 1, box.bottom - 2);
  261.     ::LineTo(box.right - 2, box.bottom - 2);
  262.     ::MoveTo(box.left + 2, box.bottom - 3);
  263.     ::LineTo(box.right - 3, box.bottom - 3);
  264.  
  265.     ::PenNormal();
  266. }
  267.  
  268. /**************************************************************************
  269.     DrawFrame()
  270.     
  271.     Draw the button frame--it's a rect with the corner pixels knocked out
  272. **************************************************************************/
  273. void
  274. LGBIconButton::DrawFrame(void)
  275. {
  276.     Rect    box = mControl->contrlRect;
  277.     ::MoveTo(box.left + 1,box.top);
  278.     ::LineTo(box.right - 2, box.top);
  279.     ::MoveTo(box.right - 1, box.top + 1);
  280.     ::LineTo(box.right - 1, box.bottom - 2);
  281.     ::MoveTo(box.right - 2, box.bottom - 1);
  282.     ::LineTo(box.left  + 1, box.bottom - 1);
  283.     ::MoveTo(box.left, box.bottom - 2);
  284.     ::LineTo(box.left, box.top + 1);
  285. }
  286.  
  287. /**************************************************************************
  288.     EraseInsides()
  289. **************************************************************************/
  290. void
  291. LGBIconButton::EraseInsides(void)
  292. {
  293.     Rect    box = mControl->contrlRect;
  294.     ::InsetRect(&box,1,1);
  295.     ::EraseRect(&box);
  296. }
  297.  
  298. /**************************************************************************
  299.     DrawIcon()
  300. **************************************************************************/
  301. void    
  302. LGBIconButton::DrawIcon(Boolean inColor)
  303. {
  304.     Rect    iconRect    = mControl->contrlRect;
  305.     ::InsetRect(&iconRect,4,4);
  306.     
  307.     short    iconID    = mControl->contrlValue;
  308.     short    align    = atNone;    // atVerticalCenter | atHorizontalCenter;
  309.     short    transform    = ttNone;
  310.     const short    hilite = mControl->contrlHilite;
  311.     if (hilite == 255) {
  312.         transform = ttDisabled;
  313.     } else if (hilite) {
  314.         if (inColor) {
  315.             transform = ttSelected;
  316.         }
  317.     }
  318.     
  319.     ::PlotIconID(&iconRect,align,transform,iconID);
  320. }
  321.  
  322. /**************************************************************************
  323.     DrawColor()
  324.     
  325.     Draw the control in color, either active or inactive
  326. **************************************************************************/
  327. void
  328. LGBIconButton::DrawColor(void)
  329. {
  330.     if (mControl->contrlHilite == 255) {
  331.         DrawColorInactive();
  332.     } else {
  333.         DrawColorActive();
  334.     }
  335.     
  336.     // restore the pen
  337.     ::PenNormal();
  338.     UGBDraw::PenReallyNormal();
  339. }
  340.  
  341. /**************************************************************************
  342.     DrawColorInactive()
  343.     
  344.     Draw the control in color, inactive. It's flattened out (no 3D
  345.     effects), and uses a greyer shade of pale for the frame.
  346. **************************************************************************/
  347. void
  348. LGBIconButton::DrawColorInactive(void)
  349. {
  350.     UGBDraw::PenFrameInactive();
  351.     DrawFrame();
  352.     
  353.     UGBDraw::Background();
  354.     EraseInsides();
  355.     
  356.     DrawIcon();
  357. }
  358.  
  359. /**************************************************************************
  360.     DrawColorActive()
  361.     
  362.     Draw the control in color, active. Draw 3D effects.
  363. **************************************************************************/
  364. void
  365. LGBIconButton::DrawColorActive(void)
  366. {
  367.     UGBDraw::PenFrameActive();
  368.     DrawFrame();
  369.     
  370.             
  371.     if (mControl->contrlHilite) {
  372.         // setup background color for highlighted fill
  373.         UGBDraw::BackGrey(UGBDraw_grey8);
  374.     } else {
  375.         // setup background color for normal (unhighlighted) fill
  376.         UGBDraw::Background();
  377.     }
  378.     EraseInsides();
  379.     
  380.     DrawIcon();
  381.     
  382.     Draw3DEffects();
  383. }
  384.  
  385. /**************************************************************************
  386.     Draw3DEffects()
  387.     
  388.     Draw the spiffy 3D effects. This function should only be called
  389.     when 1) you know you have 8 or more bits of color, and 2) the
  390.     button is active
  391. **************************************************************************/
  392. void
  393. LGBIconButton::Draw3DEffects(void)
  394. {
  395.     if (mControl->contrlHilite) {    // draw highlighted
  396.         {    // ouside edge
  397.             Rect    box    = mControl->contrlRect;
  398.             ::InsetRect(&box,1,1);
  399.             
  400.             // top left shadow
  401.             UGBDraw::ForeGrey(UGBDraw_grey4);
  402.             ::MoveTo(box.left, box.bottom - 2);
  403.             ::LineTo(box.left, box.top);
  404.             ::LineTo(box.right - 2, box.top);
  405.             
  406.             // bottom right unshadow
  407.             UGBDraw::ForeGrey(UGBDraw_greyC);
  408.             ::MoveTo(box.left, box.bottom - 1);
  409.             ::LineTo(box.right - 1, box.bottom - 1);
  410.             ::LineTo(box.right - 1, box.top);
  411.             
  412.             // top left corner
  413.             UGBDraw::ForeGrey(UGBDraw_grey2);
  414.             ::MoveTo(box.left, box.top);
  415.             ::Line(0,0);
  416.             
  417.             // top right corner
  418.             UGBDraw::ForeGrey(UGBDraw_grey7);
  419.             ::MoveTo(box.right - 1, box.top);
  420.             ::Line(0,0);
  421.                         
  422.             // bottom left corner
  423.             UGBDraw::ForeGrey(UGBDraw_grey7);
  424.             ::MoveTo(box.left, box.bottom - 1);            
  425.             ::Line(0,0);
  426.  
  427.             // bottom right corner
  428.             UGBDraw::ForeGrey(UGBDraw_greyC);
  429.             ::MoveTo(box.right - 1, box.bottom - 1);
  430.             ::Line(0,0);
  431.         }
  432.         
  433.         {    // inside edge
  434.             Rect    box    = mControl->contrlRect;
  435.             ::InsetRect(&box,2,2);
  436.             
  437.             // top left shadow
  438.             UGBDraw::ForeGrey(UGBDraw_grey5);
  439.             ::MoveTo(box.left, box.bottom - 2);
  440.             ::LineTo(box.left, box.top);
  441.             ::LineTo(box.right - 2, box.top);
  442.             
  443.             // bottom right unshadow
  444.             UGBDraw::ForeGrey(UGBDraw_greyA);
  445.             ::MoveTo(box.left, box.bottom - 1);
  446.             ::LineTo(box.right - 1, box.bottom - 1);
  447.             ::LineTo(box.right - 1, box.top);
  448.  
  449.             // top left corner
  450.             UGBDraw::ForeGrey(UGBDraw_grey4);
  451.             ::MoveTo(box.left, box.top);
  452.             ::Line(0,0);
  453.             
  454.             // top right corner
  455.             UGBDraw::ForeGrey(UGBDraw_grey8);
  456.             ::MoveTo(box.right - 1, box.top);
  457.             ::Line(0,0);
  458.             
  459.             // bottom left corner
  460.             UGBDraw::ForeGrey(UGBDraw_grey8);
  461.             ::MoveTo(box.left, box.bottom - 1);            
  462.             ::Line(0,0);
  463.             
  464.             // bottom right corner
  465.             UGBDraw::ForeGrey(UGBDraw_greyD);
  466.             ::MoveTo(box.right - 1, box.bottom - 1);
  467.             ::Line(0,0);
  468.         }
  469.     } else {                        // draw unhighlighted
  470.         {    // ouside edge
  471.             Rect    box    = mControl->contrlRect;
  472.             ::InsetRect(&box,1,1);
  473.             
  474.             // top left unshadow
  475.             UGBDraw::ForeGrey(UGBDraw_greyD);
  476.             ::MoveTo(box.left, box.bottom - 2);
  477.             ::LineTo(box.left, box.top);
  478.             ::LineTo(box.right - 2, box.top);
  479.             
  480.             // bottom right shadow
  481.             UGBDraw::ForeGrey(UGBDraw_grey7);
  482.             ::MoveTo(box.left, box.bottom - 1);
  483.             ::LineTo(box.right - 1, box.bottom - 1);
  484.             ::LineTo(box.right - 1, box.top);
  485.             
  486.             // top left corner
  487.             UGBDraw::ForeGrey(UGBDraw_greyF);
  488.             ::MoveTo(box.left, box.top);
  489.             ::Line(0,0);
  490.             
  491.             // top right corner
  492.             UGBDraw::ForeGrey(UGBDraw_greyC);
  493.             ::MoveTo(box.right - 1, box.top);
  494.             ::Line(0,0);
  495.                         
  496.             // bottom left corner
  497.             UGBDraw::ForeGrey(UGBDraw_greyC);
  498.             ::MoveTo(box.left, box.bottom - 1);            
  499.             ::Line(0,0);
  500.  
  501.             // bottom right corner
  502.             UGBDraw::ForeGrey(UGBDraw_grey4);
  503.             ::MoveTo(box.right - 1, box.bottom - 1);
  504.             ::Line(0,0);
  505.         }
  506.         
  507.         {    // inside edge
  508.             Rect    box    = mControl->contrlRect;
  509.             ::InsetRect(&box,2,2);
  510.             
  511.             // top left shadow
  512.             UGBDraw::ForeGrey(UGBDraw_greyF);
  513.             ::MoveTo(box.left, box.bottom - 2);
  514.             ::LineTo(box.left, box.top);
  515.             ::LineTo(box.right - 2, box.top);
  516.             
  517.             // bottom right unshadow
  518.             UGBDraw::ForeGrey(UGBDraw_grey8);
  519.             ::MoveTo(box.left, box.bottom - 1);
  520.             ::LineTo(box.right - 1, box.bottom - 1);
  521.             ::LineTo(box.right - 1, box.top);
  522.  
  523.             // top left corner
  524.             UGBDraw::ForeGrey(UGBDraw_greyF);
  525.             ::MoveTo(box.left, box.top);
  526.             ::Line(0,0);
  527.             
  528.             // top right corner
  529.             UGBDraw::ForeGrey(UGBDraw_greyC);
  530.             ::MoveTo(box.right - 1, box.top);
  531.             ::Line(0,0);
  532.             
  533.             // bottom left corner
  534.             UGBDraw::ForeGrey(UGBDraw_greyC);
  535.             ::MoveTo(box.left, box.bottom - 1);            
  536.             ::Line(0,0);
  537.             
  538.             // bottom right corner
  539.             UGBDraw::ForeGrey(UGBDraw_grey5);
  540.             ::MoveTo(box.right - 1, box.bottom - 1);
  541.             ::Line(0,0);
  542.         }
  543.     }
  544. }
  545.